Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #141 +/- ##
==========================================
+ Coverage 90.59% 90.63% +0.03%
==========================================
Files 41 41
Lines 1935 1943 +8
==========================================
+ Hits 1753 1761 +8
Misses 182 182 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Hmmm this may require some thought on how to standardise. PVAIn pva I set the command widget to true while the command is running, then false after it has finished. FastCS/src/fastcs/transport/epics/pva/_pv_handlers.py Lines 53 to 90 in 1cce8ea This means that I don't mind changing this to do blocking until the command is complete, but if so we should agree on this as a standard. Unless I'm mistaken, the pva analogue of the above would be to # Flip to true after the command ends
alarm_states = await self._run_command()
pv.post({"value": True, **p4p_timestamp_now(), **alarm_states})
op.done()and remove the |
|
I could imagine you might want either... so it probably needs to be a flag on |
I was thinking the same, though we probably want it to be a kwarg of type: class CommandMode(enum.Enum):
#: Command value becomes `True` in the transport only
#: once the command starts, becomes `False` after it
#: finishes.
CONTINUE_AFTER_START = "CONTINUE_ONCE_STARTED"
#: Command value becomes `True` in the transport only after
#: the command has finished. Becomes `False` immediately after.
CONTINUE_AFTER_FINISH = "CONTINUE_AFTER_FINISH" |
|
I think |
|
Yea that's much nicer. class CommandMode(enum.Enum):
#: Command value becomes `True` in the transport once
#: the command starts, becomes `False` after it finishes.
HIGH_AFTER_START = "HIGH_AFTER_START"
#: Command value becomes `True` in the transport only after
#: the command has finished. Becomes `False` immediately after.
HIGH_AFTER_FINISH = "HIGH_AFTER_FINISH" |
|
@shihab-dls is there an issue to do with arming eiger that this would fix? |
This should unblock #551, where the Eiger's |
|
@coretl @DominicOram do you have any thoughts on the behaviour we might want here? |
|
I've just pushed some rough commits outlining the behaviour we're describing (to my understanding). @GDYendell and @evalott100 did I follow correctly? Happy to revert the changes if it's decided |
|
I think we always want So the order should be:
|
|
So we don't need the option @shihab-dls, it should always do Action(blocking=True) and the pva version should be updated to match @coretl's description above. |
This would be equivalent to what we have in the PVA transport right now, so long as we swap the done around to be after everything in the CommandPvHandler: # Flip to true once command task starts
pv.post({"value": True, **p4p_timestamp_now(), **p4p_alarm_states()})
alarm_states = await self._run_command()
pv.post({"value": False, **p4p_timestamp_now(), **alarm_states})
op.done()
else:
raise RuntimeError("Commands should only take the value `True`.")This causes the behavior we expect for commands: async def do_nothing():
print("STARTED COMMAND")
await asyncio.sleep(10)
print("ENDED COMMAND")
class ControllerLongNames(Controller):
command_short_name = Command(do_nothing)
[:(] pvput -w 5 MEH:CommandShortName true
Old : 2025-03-21 14:24:35.584 false
Put timeout
SuggestionFor equivalence to the p4p backend we change from using a
|
I don't think this is what you found, is it @shihab-dls ? |
I've been testing this out; it seems it is true that the record value is set immediately, which means that: @command()
async def comm(self):
print("Started command")
await asyncio.sleep(5)
print("Finished command")with $ pvput -w 1 blah:Comm 1
Old : 2025-03-24 10:45:27.418 (0)
New : 2025-03-24 10:48:52.454 (1) where the put does not timeout. Similarly, a pvget results in: $ pvget -w 1 blah:Comm
blah:Comm 2025-03-24 10:50:21.889 (1)where the new record value is immediately available. However, the operation completion is only triggered after the callback completes, which mean monitors are updated after the callback: $ pvput -w 1 blah:Comm 1
Old : 2025-03-24 11:03:32.414 (0)
New : 2025-03-24 11:03:52.857 (1)$ pvmonitor blah:Comm
blah:Comm 2025-03-24 11:03:32.414 (0) where the monitor does not update until 5 seconds later: $ pvmonitor blah:Comm
blah:Comm 2025-03-24 11:03:32.414 (0)
blah:Comm 2025-03-24 11:03:57.858 (1)If you were to
for example: followed by: which I believe is why @evvaaaa wants us using
It seems, however, that a put with callback waits for server processing to be complete, which means that it correctly waits for the TLDRSetting
This means a However, the records
Which means that doing a put with callback will correctly wait for callback completion before returning. |
I don't have much to contribute to the details of this but I agree with @coretl that the callback should only return on the process being completed. Otherwise we have no reliable way to tell something has completed from the client side. If a client chooses not to wait for that callback then that's up to individual clients |
|
These final commits should now have this PR doing the following:
which should have our put callbacks, regardless of backend, return after a bound method has completed. |
Note that is for CA via the pythonSoftIOC transport, and PVA via the p4p transport. PVA via the pythonSoftIOC transport currently doesn't wait for completion due to epics-base/pvxs#105. This is not a blocker for FastCS (as we will use PVA via the p4p transport, so will probably turn it off in pythonSoftIOC via DiamondLightSource/pythonSoftIOC#185), but we will need this later for areaDetector IOCs when we go full PVA on beamlines. |
GDYendell
left a comment
There was a problem hiding this comment.
I think this looks good now. I suggest we have a brief discussion in the stand up to make sure we are in agreement and then merge.
|
We should make sure that we match the behaviour of the IOCs, so if we |
Looks like with $ time pvput -r "record[block=true]" -w 10 blah:Comm 1
Old : <undefined> INVALID DRIVER UDF (0)
New : 2025-03-26 12:29:02.427 (1)
real 0m5.009swhere we timeout if $ time pvput -r "record[block=true]" -w 4 blah:Comm 1
Old : 2025-03-26 12:32:44.686 (0)
Put timeout
real 0m4.009sbut the value is changed when we check afterwards: $ pvget blah:Comm
blah:Comm 2025-03-26 12:33:02.479 (1)Blocking Behaviour Post Merge:
Is this the behaviour that was agreed upon, @coretl and @GDYendell? Where P4P waits for callback completion regardless of additional flags (where -w is sort of required to ensure no timeout)? |
|
After pythonSoftIOC #186, behaviour will be:
Where Current PR behaviour:
Which should better match epics-base/pvxs#105 (comment) |
This reverts commit 862ea4c.
|
PR should be ready for re-review now. Note: |
When we put to a command PV, the put returns immediately, not waiting for the bound callback to complete. Adding the
blocking=Trueflag sets the PVsPACTfield high until the bound callback sets the PVs status to completed. This should allow an ophyd-asyncSignalXto be properly awaited.I'm not sure if this behaviour should be set like this, however; is it always the case we'd want to wait for a callback when processing a command PV?